
<style scoped lang="scss">
.attachment-main {
  display: flex;
  min-height: 400px;
  .category-main {
    width: 300px;
    border-right: 1px solid #dedede;
    padding-right: 10px;
    .custom-tree-node {
      padding-right: 10px;
      width: 100%;
      display: flex;
      flex-direction: row;
      justify-content: space-between;
    }
  }
  .image-list-main {
    width: 700px;
    margin-right: 20px;
    margin-left: 20px;
    .operation-button-box {

    }
    .image-list-box {
      display: grid;
      grid-template-columns: repeat(5, calc(20% - 20px));
      grid-gap: 20px;
      margin-top: 20px;
      .image-item {
        width: 110px;
        height: 135px;
        cursor: pointer;
        .img {
          width: 110px;
          height: 110px;
          text-align: center;
          background-color: #f8f8f8;
          div {
            display: flex;
            justify-content: center;
            align-items: center;
            width: 110px;
            height: 110px;
          }
        }
        .checked {
          border: 2px solid #1890ff;
        }
        .image-item-operation{
          .image-name {

          }
        }
      }
    }
  }
}
.ellipsis-line {
  overflow: hidden;
  text-overflow: ellipsis; //文本溢出显示省略号
  white-space: nowrap; //文本不会换行
}
.pagination-container {
  padding: 32px 0 0 0;
}

.checked-image {
  background-color: #dedede;
  padding: 10px;
  cursor: pointer;
  border: 1px dotted rgba(0,0,0,.1);
  border-radius: 4px;
  background: rgba(0,0,0,.02);
  font-size: 28px;
  color: rgba(0,0,0,0.4);
  text-align: center;
  border-radius: 5px;
}
.checked-image-tip{
  font-size: 14px;
  color: #999;
}
.checked-image-form {
  display: flex;
  flex-direction: row;
  flex-flow: wrap;
  .checked-image-item {
    position: relative;
    margin-right: 10px;
    .image{
      border-radius: 5px;
    }
    .btndel {
      cursor: pointer;
      position: absolute;
      z-index: 1;
      font-size: 18px;
      right: -5px;
      top: -5px;
      color: #999;
    }
  }
}
</style>

<template>
  <div class="attachment-box-main">
    <div class="checked-image-form">
      <template v-for="(item,index) in formImageList">
        <div v-if="index < showImageMaxCount" :key="index" class="checked-image-item">
          <el-image
            class="image"
            :src="item"
            fit="fit"
            :preview-src-list="formImageList"
            :style="{width: imageWidth, height: imageHeight}"
          />
          <i class="el-icon-error btndel" @click="delFormImage(index)" />
        </div>
      </template>
      <div v-if="formImageList.length<maxCount" class="checked-image el-icon-picture-outline" @click="openCheckImageDialog" />
    </div>
    <span class="checked-image-tip">{{ imageTip }}</span>
    <el-dialog v-el-drag-dialog title="上传文件" :visible.sync="showAttachmentDialog" append-to-body :close-on-click-modal="false" width="1000px">
      <div class="attachment-main">
        <div class="category-main">
          <el-tree
            ref="categoryTree"
            :data="categories"
            highlight-current
            check-on-click-node
            show-checkbox
            default-expand-all
            node-key="id"
            :props="{children: 'children', label: 'name', value: 'id'}"
            @check-change="categoryCheckChange"
          >
            <span slot-scope="{ node }" class="custom-tree-node">
              <span>{{ node.label }}</span>
              <el-dropdown @command="clickCategoryNode">
                <span class="el-icon-more" />
                <el-dropdown-menu slot="dropdown">
                  <el-dropdown-item :command="{command: 'add', data: node.data}">添加分类</el-dropdown-item>
                  <el-dropdown-item :command="{command: 'edit', data: node.data}">编辑分类</el-dropdown-item>
                  <el-dropdown-item :command="{command: 'del', data: node.data}">删除分类</el-dropdown-item>
                </el-dropdown-menu>
              </el-dropdown>
            </span>
          </el-tree>
        </div>
        <div class="image-list-main">
          <div class="operation-button-box">
            <el-button :disabled="checkedImageIndexList.length<=0" type="primary" size="small" @click="useCheckedImage">使用选中的图片</el-button>
            <el-button type="primary" size="small" @click="openUploadDialog">上传新图片</el-button>
            <el-button :disabled="checkedImageIndexList.length<=0" size="small" @click="delImage">删除图片</el-button>
          </div>
          <div class="image-list-box">
            <div v-for="(item,index) in imageList" :key="index" class="image-item">
              <el-badge :value="item.checked_index" :hidden="item.checked_index<=0" class="item" type="primary" @click.native="checkedImage(item,index)">
                <el-image class="img" fit="contain" :class="{ checked: item.checked_index > 0 }" :src="item.file_url">
                  <div slot="error" class="image-slot image-empty">
                    <i class="el-icon-picture-outline" />
                  </div>
                </el-image>
              </el-badge>
              <div class="image-item-operation">
                <el-tooltip class="image-name ellipsis-line" :content="item.name" placement="bottom" effect="light">
                  <div>{{ item.name }}</div>
                </el-tooltip>

              </div>
            </div>
          </div>
          <pagination :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.page_size" style="margin-top: 20px;" @pagination="getFileList" />
        </div>

        <el-dialog v-el-drag-dialog title="图片分类" :visible.sync="categoryFormDialogVisible" :close-on-click-modal="false" append-to-body width="400px">
          <el-form ref="categoryForm" :model="categoryForm" :rules="categoryFormRules" label-width="100px" label-position="left">
            <el-form-item label="上级分类" prop="parent_id">
              <el-cascader
                v-model="categoryForm.parent_id"
                :options="categories"
                :props="{ value: 'id', label: 'name', checkStrictly: true, emitPath: false }"
                style="width: 100%"
                clearable
                filterable
              />
            </el-form-item>
            <el-form-item label="分类名称" prop="name">
              <el-input v-model.trim="categoryForm.name" clearable />
            </el-form-item>
            <el-form-item>
              <el-button v-if="categoryForm.id<=0" type="primary" icon="el-icon-circle-check" @click="categorySubmit()">提交</el-button>
              <el-button v-else type="primary" icon="el-icon-circle-check" @click="categoryEditSubmit()">提交</el-button>
            </el-form-item>
          </el-form>
        </el-dialog>

        <el-dialog v-el-drag-dialog title="上传新图片" append-to-body class="upload-dialog" :visible.sync="uploadDialogVisible" :close-on-click-modal="false" width="60%" @close="closeUploadDialog">
          <el-upload
            ref="uploadImage"
            action="/admin/attachment/attachment/upload"
            list-type="picture-card"
            :data="{dir: 'product', upload_type: 1}"
            :on-preview="handlePictureCardPreview"
            :on-success="imageUploadSuccess"
            :on-error="imageUploadError"
            :auto-upload="false"
            multiple
          >
            <i class="el-icon-plus" />
            <div slot="tip" class="el-upload__tip" style="color: red">支持批量上传，只能上传jpg/png文件，且不超过500kb</div>
          </el-upload>

          <el-dialog title="图片预览" :visible.sync="pictureCardPreviewDialogVisible" append-to-body :close-on-click-modal="false">
            <img width="100%" :src="pictureCardPreviewImagePath" alt="">
          </el-dialog>

          <div slot="footer" class="dialog-footer">
            <el-button @click="closeUploadDialog">关闭</el-button>
            <el-button type="primary" @click="submitUpload">确认上传</el-button>
          </div>
        </el-dialog>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import { getFileCategoryTree, createFileCategory, updateFileCategory, deleteFileCategory, getFileList, deleteFile } from '@/api/system/file'
import Pagination from '@/components/Pagination/index.vue'
import elDragDialog from '@/directive/el-drag-dialog'
import { deepClone } from '@/utils'

export default {
  name: 'AttachmentUpload',
  directives: { elDragDialog },
  components: { Pagination },
  props: {
    // 需要获取的照片数量
    maxCount: {
      type: Number,
      default: 0
    },
    // 图片上传上的文字提示
    imageTip: {
      type: String,
      default: '建议上传图片最大宽度750px，不超过3MB；仅支持jpeg、png格式'
    },
    // 序号
    uploadIndex: {
      type: Number,
      default: 0
    },
    // 需要展示几张图片
    showImageMaxCount: {
      type: Number,
      default: 100
    },
    imageWidth: {
      type: String,
      default: '55px'
    },
    imageHeight: {
      type: String,
      default: '55px'
    },
    imageUrlList: {
      type: Array,
      default: function() {
        return []
      }
    },
    imagePathList: {
      type: Array,
      default: function() {
        return []
      }
    }
  },
  data() {
    return {
      categories: [],
      imageList: [],
      total: 0,
      listQuery: {
        page: 1,
        page_size: 15,
        attachment_category_ids: []
      },
      categoryFormDialogVisible: false,
      categoryForm: {
        id: 0,
        parent_id: 0,
        name: null
      },
      categoryFormRules: {
        name: [
          { required: true, message: '请输入', trigger: 'blur' }
        ]
      },
      checkedImageIndexList: [], // 点击时选择的图片序号
      formImageList: [], // 表单组件中存放的图片完整url，提供展示
      formImagePathList: [], // 表单组件中存放的图片相对地址，实际要返回的表单内图片地址信息
      uploadDialogVisible: false,
      uploadFileList: [],
      pictureCardPreviewDialogVisible: false,
      pictureCardPreviewImagePath: null,
      showAttachmentDialog: false
    }
  },
  created() {
    // 加载初始展示的图片
    if (this.imageUrlList.length > 0) {
      this.formImageList = deepClone(this.imageUrlList)
    }
    if (this.imagePathList.length > 0) {
      this.formImagePathList = deepClone(this.imagePathList)
    }
  },
  methods: {
    getBaseData() {
      this.getCategories()
      this.getFileList()
    },
    getCategories() {
      getFileCategoryTree().then(res => {
        const data = [
          {
            id: 0,
            name: '全部图片',
            children: res.data
          }
        ]
        this.categories = data
      })
    },
    getFileList() {
      getFileList(this.listQuery).then(res => {
        this.imageList = res.list
        this.total = res.total
      })
    },
    categoryCheckChange(data, checked, indeterminate) {
      const ids = []
      this.$refs.categoryTree.getCheckedNodes().map(item => {
        ids.push(item.id)
      })
      this.listQuery.attachment_category_ids = ids
      this.getFileList()
    },
    checkedImage(row, index) {
      const listIndex = this.checkedImageIndexList.indexOf(row.id)
      if (listIndex > -1) {
        // 删除
        this.checkedImageIndexList.splice(listIndex, 1)
      } else {
        // 添加
        if (this.checkedImageIndexList.length >= this.maxCount) {
          this.$message({
            message: `最多选${this.maxCount}张`,
            type: 'warning'
          })
          return false
        } else {
          this.checkedImageIndexList.push(row.id)
        }
      }

      this.flushImageCheckedIndexNumber()
    },
    flushImageCheckedIndexNumber() {
      this.imageList.forEach(item => {
        const checkedIndex = this.checkedImageIndexList.indexOf(item.id)
        if (checkedIndex > -1) {
          this.$set(item, 'checked_index', checkedIndex + 1)
        } else {
          this.$set(item, 'checked_index', 0)
        }
      })
    },
    categorySubmit() {
      this.$refs['categoryForm'].validate((valid) => {
        if (valid) {
          createFileCategory(this.categoryForm).then(res => {
            this.categoryFormDialogVisible = false
            this.getCategories()
            this.$message({
              message: res.message,
              type: 'success'
            })
          })
        }
      })
    },
    categoryEditSubmit() {
      this.$refs['categoryForm'].validate((valid) => {
        if (valid) {
          updateFileCategory(this.categoryForm).then(res => {
            this.categoryFormDialogVisible = false
            this.getCategories()
            this.$message({
              message: res.message,
              type: 'success'
            })
          })
        }
      })
    },
    clickCategoryNode(row) {
      if (row.command === 'add') {
        this.openAddCategoryForm(row.data)
      } else if (row.command === 'edit') {
        this.openEditCategoryForm(row.data)
      } else if (row.command === 'del') {
        this.delCategory(row.data)
      }
    },
    openAddCategoryForm(row) {
      this.categoryForm = {
        id: 0,
        parent_id: 0,
        name: null
      }
      if (row.id > 0) {
        this.categoryForm.parent_id = row.id
      }
      this.categoryFormDialogVisible = true
    },
    openEditCategoryForm(row) {
      this.categoryForm.id = row.id
      this.categoryForm.parent_id = row.parent_id
      this.categoryForm.name = row.name
      this.categoryFormDialogVisible = true
    },
    delCategory(row) {
      if (row.id === 0) {
        this.$message('顶级分类无法删除')
        return
      }
      this.$confirm(`确定要删除[${row.name}]分类吗？`, '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        deleteFileCategory({ id: row.id }).then(res => {
          this.getCategories()
          this.$message({
            message: res.message,
            type: 'success'
          })
        })
      }).catch(() => {
        this.$message('您已取消')
      })
    },
    openCheckImageDialog() {
      // 打开图片选择弹窗
      this.showAttachmentDialog = true
      this.checkedImageIndexList = []
      this.getBaseData()
      this.flushImageCheckedIndexNumber()
    },
    closeCheckImageDialog() {
      // 关闭图片选择弹窗
      this.showAttachmentDialog = false
      this.checkedImageIndexList = []
    },
    useCheckedImage() {
      // 整理返回选择的图片相对路径
      this.imageList.forEach(item => {
        const checkedIndex = this.checkedImageIndexList.indexOf(item.id)
        if (checkedIndex > -1) {
          // 若当前新选择图片数量大于 maxCount 则自动去掉多余的图片
          if (this.formImageList.length < this.maxCount) {
            this.formImagePathList.push(item.path)
            this.formImageList.push(item.url)
          }
        }
      })

      // 将表单中展示的图片信息返回给父组件
      if (this.formImagePathList.length === 0) {
        return false
      }
      this.pushFormImagePath()

      // 关闭图片选择弹窗
      this.closeCheckImageDialog()
    },
    imageUploadSuccess(res, file, fileList) {
      console.log(res, file, fileList)
      if (res && res.code === 0) {
        // this.$message({
        //   message: `图片【${res.data.name}】上传成功！`,
        //   type: 'success'
        // })
      } else {
        // 删除上传失败的图片 TODO: 待优化上传失败文件从成功的列表中移除
        this.$message({
          message: `文件【${file.name}】上传失败：${res.message || '文件上传失败'}`,
          type: 'error'
        })
      }
      this.getFileList()
    },
    imageUploadError(err, file, fileList) {
      console.log('imageUploadError', err)
      this.$message({
        message: err || '文件上传失败',
        type: 'error'
      })
    },
    handlePictureCardPreview(file) {
      this.pictureCardPreviewImagePath = file.url
      this.pictureCardPreviewDialogVisible = true
    },
    submitUpload() {
      this.$refs.uploadImage.submit()
    },
    openUploadDialog() {
      this.uploadDialogVisible = true
    },
    closeUploadDialog() {
      this.$refs.uploadImage.clearFiles()
      this.uploadDialogVisible = false
    },
    delImage() {
      this.$confirm(`确定要删除 ${this.checkedImageIndexList.length} 张图片吗？`, '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        deleteFile({ ids: this.checkedImageIndexList }).then(res => {
          this.getFileList()
          this.$message({
            message: res.message,
            type: 'success'
          })
        })
      }).catch(() => {
        this.$message('您已取消')
      })
    },
    delFormImage(index) {
      this.formImageList.splice(index, 1)
      this.formImagePathList.splice(index, 1)
      this.pushFormImagePath()
    },
    pushFormImagePath() {
      // 将最新的表单数据推送到父组件
      if (this.maxCount === 1) {
        this.$emit('checkedFile', this.formImagePathList[0], this.uploadIndex)
      } else {
        this.$emit('checkedFile', this.formImagePathList, this.uploadIndex)
      }
    }
  }
}
</script>
